package com.parking.mgr.useraccount.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.parking.mgr.common.constant.CommonConstant;
import com.parking.mgr.common.exception.LoginAuthException;
import com.parking.mgr.common.exception.enums.AuthExceptionEnum;
import com.parking.mgr.common.util.IdUtils;
import com.parking.mgr.common.util.TimestampUtil;
import com.parking.mgr.useraccount.model.entity.LoginTokenEntity;
import com.parking.mgr.useraccount.model.mapper.LoginTokenMapper;
import com.parking.mgr.useraccount.model.mapstruct.LoginTokenMapStruct;
import com.parking.mgr.useraccount.model.param.LoginTokenParam;
import com.parking.mgr.useraccount.model.vo.LoginTokenVO;
import com.parking.mgr.useraccount.service.LoginTokenService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * @ClassName LoginTokenServiceImpl
 * @Description 登录令牌service实现类
 * @Auther: zhijianpu
 * @Date: 2023/5/25
 */
@Log4j2
@Service
public class LoginTokenServiceImpl extends ServiceImpl<LoginTokenMapper, LoginTokenEntity> implements LoginTokenService {

    @Resource
    private LoginTokenMapper loginTokenMapper;

    @Resource
    private LoginTokenMapStruct loginTokenMapStruct;

    @Override
    public void add(LoginTokenParam loginTokenParam, HttpServletRequest request) {

        LoginTokenEntity loginTokenEntity = new LoginTokenEntity();
        // 如果找到client_id，延期15天
        loginTokenEntity.setFExpireTimeMillis(TimestampUtil.extensionDays());
        loginTokenEntity.setFClientId(loginTokenParam.getFClientId());
        loginTokenEntity.setFCreateTimeMillis(TimestampUtil.createTimestamp());
        loginTokenEntity.setFUserAgent(ServletUtil.getHeaderIgnoreCase(request, CommonConstant.USER_AGENT));
        loginTokenEntity.setId(IdUtils.getId());

        this.save(loginTokenEntity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateExpireTime(LoginTokenParam loginTokenParam) {
        this.update(new LambdaUpdateWrapper<LoginTokenEntity>()
                .eq(LoginTokenEntity::getFClientId, loginTokenParam.getFClientId())
                .set(LoginTokenEntity::getFExpireTimeMillis, loginTokenParam.getFExpireTimeMillis()));
    }

    @Override
    public void updateToken(String token, String passportId, String clientId) {
        LambdaUpdateWrapper<LoginTokenEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(LoginTokenEntity::getFClientId, clientId)
                .set(LoginTokenEntity::getFLoginToken, token)
                .set(LoginTokenEntity::getFkUserPassportId, passportId);
        this.update(updateWrapper);
    }

    @Override
    public LoginTokenEntity queryLoginTokenByPassportId(String passportId) {
        LoginTokenEntity loginTokenEntity = loginTokenMapper.selectOne(new LambdaQueryWrapper<LoginTokenEntity>()
                .eq(LoginTokenEntity::getFkUserPassportId, passportId));
        return loginTokenEntity;
    }

    @Override
    public String queryPassportByClientIdToken(String token, String clientId) {
        if (StrUtil.isEmpty(clientId) || StrUtil.isEmpty(token)) {
            throw new LoginAuthException(AuthExceptionEnum.CLIENT_ID_OR_TOKEN_EMPTY.getMessage());
        }
        LoginTokenEntity loginTokenEntity = loginTokenMapper.selectOne(new LambdaQueryWrapper<LoginTokenEntity>()
                .eq(LoginTokenEntity::getFLoginToken, token)
                .eq(LoginTokenEntity:: getFClientId, clientId));

        if (ObjectUtil.isNull(loginTokenEntity)) {
            throw new LoginAuthException(AuthExceptionEnum.NO_LOGIN_USER.getMessage());
        }
        return loginTokenEntity.getFkUserPassportId();
    }

    @Override
    public String getPassportIdByToken(HttpServletRequest request) {
        String clientId = request.getHeader(CommonConstant.CLIENT_ID);
        String loginToken = request.getHeader(CommonConstant.LOGIN_TOKEN);
        if (StrUtil.isEmpty(clientId) || StrUtil.isEmpty(loginToken)) {
            throw new LoginAuthException(AuthExceptionEnum.CLIENT_ID_OR_TOKEN_EMPTY.getMessage());
        }
        LoginTokenEntity loginTokenEntity = loginTokenMapper.selectOne(new LambdaQueryWrapper<LoginTokenEntity>()
                .eq(LoginTokenEntity::getFLoginToken, loginToken)
                .eq(LoginTokenEntity:: getFClientId, clientId));

        if (ObjectUtil.isNull(loginTokenEntity)) {
            throw new LoginAuthException(AuthExceptionEnum.NO_LOGIN_USER.getMessage());
        }
        return loginTokenEntity.getFkUserPassportId();
    }

    @Override
    public String getTokenId(String token, String clientId) {

        if (StringUtils.isEmpty(clientId) || StringUtils.isEmpty(token)) {
            throw new LoginAuthException(AuthExceptionEnum.CLIENT_ID_OR_TOKEN_EMPTY.getMessage());
        }

        LoginTokenEntity loginTokenEntity = loginTokenMapper.selectOne(new LambdaQueryWrapper<LoginTokenEntity>()
                .eq(LoginTokenEntity::getFClientId, clientId)
                .eq(LoginTokenEntity::getFLoginToken, token));

        if (ObjectUtil.isNull(loginTokenEntity)) {
            throw new LoginAuthException(AuthExceptionEnum.NO_LOGIN_USER.getMessage());
        }

        return loginTokenEntity.getId();
    }

    @Override
    public void delete(String token, String clientId) {
        LambdaQueryWrapper<LoginTokenEntity> tokenQueryWrapper = new LambdaQueryWrapper<LoginTokenEntity>()
                .eq(LoginTokenEntity::getFClientId, clientId)
                .eq(LoginTokenEntity::getFLoginToken, token);

        loginTokenMapper.delete(tokenQueryWrapper);
    }

    @Override
    public LoginTokenEntity getLoginTokenEntity(String token, String clientId) {

        return loginTokenMapper.selectOne(new LambdaQueryWrapper<LoginTokenEntity>()
                .eq(LoginTokenEntity::getFClientId, clientId)
                .eq(LoginTokenEntity::getFLoginToken, token));
    }

    @Override
    public IPage<LoginTokenVO> list(LoginTokenParam loginTokenParam) {
        log.info("获取登录令牌列表");
        LambdaQueryWrapper<LoginTokenEntity> queryWrapper = new LambdaQueryWrapper<>();
        // 根据用户所属账号查询
        if (StrUtil.isNotEmpty(loginTokenParam.getFkUserPassportId())) {
            log.info("根据用户所属账号查询登录令牌");
            queryWrapper.eq(LoginTokenEntity::getFkUserPassportId, loginTokenParam.getFkUserPassportId());
        }

        return loginTokenMapStruct.entity2VO(this.page(new Page<>(loginTokenParam.getCurrPage(), loginTokenParam.getPageSize()), queryWrapper));
    }

    @Override
    public boolean isLoginAuth(HttpServletRequest request) {
        LoginTokenEntity loginTokenEntity = loginTokenMapper.selectOne(new LambdaQueryWrapper<LoginTokenEntity>()
                .eq(LoginTokenEntity::getFLoginToken, request.getHeader(CommonConstant.LOGIN_TOKEN))
                .eq(LoginTokenEntity::getFClientId, request.getHeader(CommonConstant.CLIENT_ID)));

        if (ObjectUtil.isNull(loginTokenEntity)) {
            return false;
        } else {
            return true;
        }
    }


}
